add readFileString, writeFileString, appendFileString
authorJoey Hess <joeyh@joeyh.name>
Fri, 5 Sep 2025 18:51:26 +0000 (14:51 -0400)
committerJoey Hess <joeyh@joeyh.name>
Fri, 5 Sep 2025 18:54:36 +0000 (14:54 -0400)
Exported by Common, so they will be available everywhere.
These are the same as readFile, writeFile, appendFile.
But have two benefits:

* They take OsPath, so using them avoids converting back and forth
  unncessarily.
* They use the close-on-exec flag so can't leak FDs to child processes.
  Unlike the standard Haskell versions which unfortunately have that
  wart currently. (I do hope the standard versions get fixed
  eventually.)

Sponsored-by: the NIH-funded NICEMAN (ReproNim TR&D3) project
Common.hs
Utility/FileIO.hs
Utility/FileIO/String.hs [new file with mode: 0644]
git-annex.cabal

index fe322fa1c4d0859ffc34615aa28ae4107444339f..8d651259652a51e27fa55458231c02fe2304eefe 100644 (file)
--- a/Common.hs
+++ b/Common.hs
@@ -33,5 +33,6 @@ import Utility.Network as X
 import Utility.Split as X
 import Utility.FileSystemEncoding as X
 import Utility.OsPath as X
+import Utility.FileIO as X (readFileString, writeFileString, appendFileString)
 
 import Utility.PartialPrelude as X
index 7c13d84925f5dbe5274fa936049c28fb12d0c4de..99ea53882349a9622342c58f3c989aeddf99d432 100644 (file)
@@ -1,6 +1,8 @@
-{- This is a subset of the functions provided by file-io.
+{- This is a subset of the functions provided by file-io, supplimented with
+ - readFileString, writeFileString, and appendFileString.
  -
- - All exported functions set the close-on-exec flag.
+ - When building with file-io, all exported functions set the close-on-exec
+ - flag.
  -
  - When not building with file-io, this provides equvilant
  - RawFilePath versions. Note that those versions do not currently
@@ -31,12 +33,17 @@ module Utility.FileIO
        appendFile,
        appendFile',
        openTempFile,
+
+       readFileString,
+       writeFileString,
+       appendFileString,
 ) where
 
 #ifdef WITH_OSPATH
 
 #ifndef mingw32_HOST_OS
 import Utility.FileIO.CloseOnExec
+import Utility.FileIO.String
 #else
 -- On Windows, System.File.OsPath does not handle UNC-style conversion itself,
 -- so that has to be done when calling it. See 
@@ -44,8 +51,9 @@ import Utility.FileIO.CloseOnExec
 import Utility.Path.Windows
 import Utility.OsPath
 import System.IO (IO, Handle, IOMode)
-import Prelude (return)
+import Prelude (String, return)
 import qualified Utility.FileIO.CloseOnExec as O
+import qualified Utility.FileIO.String as O
 import qualified Data.ByteString as B
 import Control.Applicative
 
@@ -106,6 +114,21 @@ openTempFile p s = do
        -- Avoid returning mangled path from convertToWindowsNativeNamespace
        let t' = p </> takeFileName t
        return (t', h)
+
+readFileString :: OsPath -> IO String
+readFileString p = do
+       p' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath p)
+       I.readFileString p'
+
+writeFileString :: OsPath -> String -> IO ()
+writeFileString f txt = do
+       f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
+       I.writeFileString f' txt
+
+appendFileString :: OsPath -> String -> IO ()
+appendFileString f txt = do
+       f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
+       I.appendFileString f' txt
 #endif
 
 #else
@@ -113,7 +136,8 @@ openTempFile p s = do
 import Utility.OsPath
 import Utility.FileSystemEncoding
 import System.IO (IO, Handle, IOMode)
-import Prelude ((.), return)
+import Prelude (String, (.), return)
+import qualified Prelude as P
 import qualified System.IO
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Lazy as L
@@ -154,4 +178,13 @@ openTempFile p s = do
                (fromRawFilePath p)
                (fromRawFilePath s)
        return (toRawFilePath t, h)
+
+readFileString :: OsPath -> IO String
+readFileString = P.readFile . fromRawFilePath
+
+writeFileString :: OsPath -> String -> IO ()
+writeFileString = P.writeFile . fromRawFilePath
+
+appendFileString :: OsPath -> String -> IO ()
+appendFileString = P.appendFile . fromRawFilePath
 #endif
diff --git a/Utility/FileIO/String.hs b/Utility/FileIO/String.hs
new file mode 100644 (file)
index 0000000..2159960
--- /dev/null
@@ -0,0 +1,38 @@
+{- Functions that operate on OsPath, but treat the contents of files as
+ - Strings.
+ -
+ - These functions all set the close-on-exec flag to True, unlike
+ - the Prelude versions.
+ -
+ - Copyright 2025 Joey Hess <id@joeyh.name>
+ -
+ - License: BSD-2-clause
+ -}
+
+{-# OPTIONS_GHC -fno-warn-tabs #-}
+{-# LANGUAGE CPP #-}
+
+module Utility.FileIO.String
+(
+#ifdef WITH_OSPATH
+       readFileString,
+       writeFileString,
+       appendFileString,
+#endif
+) where
+
+#ifdef WITH_OSPATH
+import qualified Utility.FileIO.CloseOnExec as I
+import Utility.OsPath (OsPath)
+import Prelude (String, IO, (>>=))
+import System.IO (IOMode(..), hGetContents, hPutStr)
+
+readFileString :: OsPath -> IO String
+readFileString f = I.openFile f ReadMode >>= hGetContents
+
+writeFileString :: OsPath -> String -> IO ()
+writeFileString f txt = I.withFile f WriteMode (\hdl -> hPutStr hdl txt)
+
+appendFileString :: OsPath -> String -> IO ()
+appendFileString f txt = I.withFile f AppendMode (\hdl -> hPutStr hdl txt)
+#endif
index efa8b275e3912628009df71c24196855abcce3ad..8591e54d9fb65ce20cd5ba3e643eecf41ff84090 100644 (file)
@@ -1149,6 +1149,7 @@ Executable git-annex
     Utility.SystemDirectory
     Utility.FileIO
     Utility.FileIO.CloseOnExec
+    Utility.FileIO.String
     Utility.Terminal
     Utility.TimeStamp
     Utility.TList